
#include <cstdlib>

#include <QtCore>

#include "ai/agent.h"
#include "ai/flock.h"
#include "core/engine.h"
#include "geometry/quadtree.h"

Agent::Agent(Flock& kFlock)
    : m_rkFlock(kFlock),
      m_bIsActive(true),
      m_kRange(0, 0, 0, 1.5, this),
      m_pkUserData(NULL)
{
}

Agent::~Agent()
{
}

bool Agent::isActive() const
{
    return m_bIsActive;
}

void Agent::setActive(bool bActive)
{
    m_bIsActive = bActive;

    if(m_bIsActive)
    {
        m_rkFlock.ranges().add(m_kRange);
    }
    else
    {
        m_rkFlock.ranges().remove(m_kRange);
    }
}

QVector3D Agent::position() const
{
    return m_kRange.center();
}

QVector3D Agent::velocity() const
{
    return m_kVelocity;
}

void Agent::setPosition(const QVector3D& rkPosition)
{
    if(m_bIsActive)
        m_rkFlock.ranges().remove(m_kRange);

    m_kRange.setPosition(rkPosition);

    if(m_bIsActive)
        m_rkFlock.ranges().add(m_kRange);
}

void Agent::setPosition(qreal x, qreal y, qreal z)
{
    setPosition(QVector3D(x, y, z));
}

void Agent::setVelocity(const QVector3D& rkVelocity)
{ 
    m_kVelocity = rkVelocity;

    // Planar clamp.
    m_kVelocity.setY(0);

    // Magnitude clamp.
    qreal lengthSquared = rkVelocity.lengthSquared();
    if(lengthSquared < qPow(s_minVelocity, 2))
    {
        m_kVelocity.normalize();
        m_kVelocity *= s_minVelocity;
        return;
    }
    else if(lengthSquared > qPow(s_maxVelocity, 2))
    {
        m_kVelocity.normalize();
        m_kVelocity *= s_maxVelocity;
    }
}

void Agent::setVelocity(qreal x, qreal y, qreal z)
{
    setVelocity(QVector3D(x, y, z));
}

const Sphere& Agent::range() const
{
    return m_kRange;
}

void* Agent::userData() const
{
    return m_pkUserData;
}

void Agent::setUserData(void* pkUserData)
{
    m_pkUserData = pkUserData;
}
